/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.ove.openmath.jome.ctrl.om;

/**
 *
 * @author Mr.Sam
 */
import java.io.*;
import java.util.*;
import fr.inria.openmath.omapi.*;
import fr.ove.openmath.jome.ctrl.linear.events.*;
import fr.ove.openmath.jome.ctrl.om.*;
import fr.ove.openmath.jome.ctrl.amto.*;

/**
* The handler for the OpenMath parser.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 19/11/1999
*/
public class OMTreeParserHandler extends ParserAdapter implements java.io.Serializable {
    /**
    * A stack for context management.
    */
    private Stack stackContext = new Stack();

    /**
    * A stack for symbol management.
    */
    private Stack stackSymbol = new Stack(); // Le sommet de cette pile représente le symbol
    // qui n'est pas une feuille dans l'arbre (donc en fait un opérateur, une fonction).
    // Ceci est utile lors de la construction pour déterminer si le pointeur courant d'insertion
    // doit être remonté lorsque l'on rencontre un tag </OMA> (il va de soit que le symbole courant
    // est empilé lorsqu'un tag <OMA> a été rencontré.
    // Ex: + est n-aire dans la formula, donc a la forme (+ a b c). Pourtant a+b+c peut être écrit en OM
    // de plusieurs façon, et surtout de façon différente à la forme de la formula. Par exemple:
    // OMA + a OMA + b c /OMA /OMA. Il ne faut pas que le ptr courant remonte d'un cran lors de la
    // rencontre du premier /OMA

    /**
    * A stack for counting the number of operands of the current symbol
    */
    private Stack stackSymbolOperands = new Stack(); // Le sommet de cette pile représente le nombre d'opérande
    // du symbol courant, i.e. celui au sommet de la pile stackSymbol.
    
    
    private OMParserResourcesManager resourcesManager;
    
    private AbstractMathTreeObject amto;
    private MathExpression mathExp;
    
    
    /**
    * The different contexts all along the parsing.
    */
    private static final byte CREATE_OBJECT             = 0;
    private static final byte WAIT_FOR_OBJECT           = 1;
    private static final byte WAIT_FOR_END_OBJECT       = 2;
    
    private static final byte CREATE_APPLICATION        = 3;
    
    private static final byte CREATE_ATTRIBUTION        = 4;
    private static final byte CREATE_ATTRIBUT_PAIRS     = 5;
    private static final byte END_ATTRIBUT_PAIRS        = 6;
    private static final byte END_ATTRIBUTION           = 7;
    
    private static final byte CREATE_ERROR              = 8;
    
    private static final byte CREATE_BIDING             = 9;
    private static final byte CREATE_BIDING_VARIABLES   = 10;
    private static final byte WAIT_FOR_VARIABLES        = 11;
    private static final byte CREATE_BIDING_OBJECT      = 12;
    private static final byte END_BIDING                = 13;
        
    private Locator locator;
    
    // nécessaire pour l'insertion d'un symbol "fictif" dans la pile pour les fonctions.
    // Au moins pour le moment.
    // si on a f(x) (donc <OMA><OMV name="f"/><OMV name="x"/></OMA>), quand on va tomber sur le
    // </OMA>, il n'y aura pas de symbole dans la pile, et donc on remontera plus que... la raison le permet.
    private boolean isApply = false;

    /**
    * The constructor.<BR>
    * formula must be the root of an empty one.
    */
    public OMTreeParserHandler() {
        resourcesManager = new OMParserResourcesManager("fr.ove.openmath.jome.ctrl.om.OMParserResources");
        mathExp = new MathExpression();
    }
    
    /**
    * Pushes the context in the stack.
    * @param context the context to push.
    */
    private void pushContext(byte context) {
        stackContext.push(new Byte(context));
    }

    /**
    * Pops the context which is on the top of the stack.
    */
    private byte popContext() {
        return ((Byte) stackContext.pop()).byteValue();
    }

    /**
    * Returns the context which is on the top of the stack.<BR>
    * The returned context still remains into the stack.
    */
    private byte getContext() {
        return ((Byte) stackContext.peek()).byteValue();
    }


    /**
    * Throws an OpenMath exception.
    * @param message the message to display.
    * @param e a specific exception to throw.
    * @see fr.inria.openmath.omapi.OMException
    */
    private void throwOME(String message, Exception e) throws OMException {
        if (locator != null) {
            throw new OMException(
                    message + " (at line:" + locator.getLineNumber() + " col:"
                    + locator.getColumnNumber() + ")", e);
        } else {
            throw new OMException(message, e);
        }
    }

    /**
    * Throws an OpenMath exception.
    * @param message the message to display.
    * @param code the code of the excpetion thrown.
    * @see fr.inria.openmath.omapi.OMException
    */
    private void throwOME(String message, short code) throws OMException {
        if (locator != null) {
            throw new OMException(
                    message + " (at line:" + locator.getLineNumber() + " col:"
                    + locator.getColumnNumber() + ")", code);
        } else {
            throw new OMException(message, code);
        }

    }

    /**
    * Throws an OpenMath exception.
    * @param message the message to display.
    * @see fr.inria.openmath.omapi.OMException
    */
    private void throwOME(String message) throws OMException {
        throwOME(message, OMException.OME_GENERIC);
    }


    /*******************************************/
    /*                                         */
    /* Les méthodes de la classe ParserAdapter */
    /*                                         */
    /*******************************************/




    /**
     * Receives a Locator for parse events.
     *
     * <p>By default, do nothing. Application writers may override this
     * method in a subclass if they wish to store the locator for use
     * with other  events.</p>
     *
     * @param locator A locator for all OpenMath parse events.
     * @see fr.inria.openmath.omapi.ParserHandler#setLocator
     * @see fr.inria.openmath.omapi.Locator
     */
    public void setLocator(Locator locator) {
    }

    /**
     * Receives notification of the beginning of parse (of a set of OpenMath-objects).
     *
     * <p>By default, do nothing. Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     */
    public void startParse() throws OMException {
    }

    /**
     * Receives notification of the end of parse.
     *
     * <p>By default, do nothing. Application writers may override this
     * method in a subclass.</p>
     *
     * <p>The OpenMath parser will invoke this method only once, and it will
     * be the last method invoked during the parse.  The parser shall
     * not invoke this method until it has either abandoned parsing
     * (because of an unrecoverable error) or reached the end of
     * the input (no more OpenMath objects).</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     */
    public void endParse() throws OMException {
    }

    /**
     * Receives notification of the beginning of a object element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #endObject
     */
    public void startObject() throws OMException {
        //TraceContext("startObject");
        stackContext.removeAllElements();
        stackSymbol.removeAllElements();
        stackSymbolOperands.removeAllElements();
        
        if (!stackContext.empty())
            throwOME("Malformed object. Unexpected start of object found", OMException.OME_SYNTAX);

        pushContext(CREATE_OBJECT);
        
        mathExp.removeAll();
        amto = mathExp;
    }

    /**
     * Receives notification of the end of an object element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #startObject
     */
    public void endObject() throws OMException {
        if (!stackContext.empty()) {
            popContext();
            
            if (!stackContext.empty())
                    throwOME("Malformed object. Something wrong occured");
        }
        else
            throwOME("Malformed object. Something wrong occured");
        
        mathExp.flush();
        mathExp.removeAll();
    }

    /**
     * Receives notification of the beginning of a application element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #endApplication
     */
    public void startApplication() throws OMException {
        if (!stackSymbol.empty()) {
            Symbol currentSymbol = (Symbol) stackSymbol.peek();
            
            // d'abord on regarde si c'est un "vrai" symbol.
            if (!currentSymbol.equals("", "")) {
                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                // On augmente le nombre d'opérandes
                numOperands++;
                
                byte arity = resourcesManager.getArity(currentSymbol.toString());
                // Si l'arité est -1, alors on a un opérateur n-aire
                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                
                if (numOperands > arity)
                    throwOME("Malformed object. Symbol arity not respected : " + currentSymbol.toString(), OMException.OME_SYNTAX);
                    
                stackSymbolOperands.push(new Byte(numOperands));
            }
        }
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_APPLICATION:
                case CREATE_BIDING_OBJECT:
                    pushContext(context);
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_BIDING:
                    pushContext(CREATE_APPLICATION);
                    break;
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of the end of an application element.
     *
     * <p>By default, do nothing. Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #startApplication
     */
    public void endApplication() throws OMException {
        Symbol symbol;  // Le symbol courant quand on entre dans cette méthode.
        Symbol topSymbol;  // Le symbol en sommet de pile quand on a enlevé le symbol courant.
                           // c'est le futur symbole courant.
                           
        //TraceContext("endApplication");
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case WAIT_FOR_OBJECT:
                    popContext(); // On enlève le contexte d'application 
                    // On récupère le symbole courant et on l'enlève de la pile
                    symbol = (Symbol) stackSymbol.pop();
                    // On enlève le nombre d'opérandes correspondant
                    stackSymbolOperands.pop();
                    
                    if (!stackContext.empty()) {
                        switch (getContext()) {
                            case CREATE_OBJECT: // a priori on n'aura jamais ça !!!!!
                                pushContext(WAIT_FOR_END_OBJECT);
                            case CREATE_APPLICATION:
                            case CREATE_ERROR:
                                amto = amto.getFather(); 
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_BIDING_OBJECT:
                                popContext();  // on enlève le contexte CREATE_BIDING_OBJECT
                                popContext();  // on enlève le contexte CREATE_BIDING
                                amto = amto.getFather();
                                pushContext(END_BIDING);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else 
                        pushContext(WAIT_FOR_END_OBJECT);
                    
                    break;
                        
                case CREATE_OBJECT:
                case CREATE_APPLICATION:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");

    }


    /**
     * Receives notification of the beginning of a attribution element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #endAttribution
     */
    public void startAttribution() throws OMException {
        
        //TraceContext("startAttribution");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case CREATE_APPLICATION:
                    // On rajoute un symbole foireux parce qu'on n'a pas créé une application à partir d'un symbol
                    // d'un CD. On n'a donc pas à tester a priori le nombre d'opérandes.
                    stackSymbol.push(new Symbol("", ""));
                    stackSymbolOperands.push(new Byte(Byte.MAX_VALUE));
                
                case CREATE_BIDING:
                case WAIT_FOR_VARIABLES:
                case CREATE_BIDING_OBJECT:
                    pushContext(context);
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                    pushContext(CREATE_ATTRIBUTION);
                    
                    /*
                    Ce qu'il faut pour l'attribution
                    */
                    
                    break;
                    
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of the end of an attribution element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #startAttribution
     */
    public void endAttribution() throws OMException {
        
        //TraceContext("endAttribution");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case END_ATTRIBUTION:
                    //System.out.println("On termine l'attribution");
                    
                    /*
                    Ce qu'il faut pour terminer l'attribution
                    */
                    
                    // Ca fait que l'on vient de lire un object.
                    // I lfaut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        switch (getContext()) {
                            case CREATE_OBJECT:
                                pushContext(WAIT_FOR_END_OBJECT);
                            case CREATE_ERROR:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case WAIT_FOR_VARIABLES:
                                popContext();  // on enlève le contexte WAIT_FOR_VARIABLES
                                pushContext(CREATE_BIDING_OBJECT);
                                break;
                            case CREATE_BIDING_OBJECT:
                                popContext();  // on enlève le contexte CREATE_BIDING_OBJECT
                                popContext();  // on enlève le contexte CREATE_BIDING
                                pushContext(END_BIDING);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else
                        pushContext(WAIT_FOR_END_OBJECT);
                        
                    break;
                    
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_APPLICATION:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
        
    }

    /**
     * Receives notification of the beginning of an attribute-pairs element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     * @see #endAttributePairs
     */
    public void startAttributePairs() throws OMException {
        //TraceContext("startAttributePairs");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case CREATE_ATTRIBUTION:
                    /*
                    Ce qu'il faut pour démarrer la paire d'attribut.
                    */
                
                    pushContext(context);
                    pushContext(CREATE_ATTRIBUT_PAIRS);
                    break;
                    
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_APPLICATION:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of the end of an attribute-pairs element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #startAttribution
     */
    public void endAttributePairs() throws OMException {
        
        //TraceContext("endAttributePairs");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case END_ATTRIBUT_PAIRS:
                    //System.out.println("On termine la paire d'attribut");
                    
                    /*
                    Ce qu'il faut pour terminer la paire d'attribut
                    */
                    
                    if (!stackContext.empty()) {
                        popContext();
                        pushContext(WAIT_FOR_OBJECT);
                    }
                    else
                        throwOME("Malformed object. Something wrong occured");
                        
                    break;
                    
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_APPLICATION:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of the beginning of a Bind element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     * @see #endBind
     */
    public void startBind() throws OMException {
        //TraceContext("startBind");
        
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case CREATE_APPLICATION:
                    // On rajoute un symbole foireux parce qu'on n'a pas créé une application à partir d'un symbol
                    // d'un CD. On n'a donc pas à tester a priori le nombre d'opérandes.
                    stackSymbol.push(new Symbol("", ""));
                    stackSymbolOperands.push(new Byte(Byte.MAX_VALUE));
                
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    pushContext(context);
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                    pushContext(CREATE_BIDING);
                    
                    /*
                    Ce qu'il faut pour créer le biding
                    */
                    
                    break;
                    
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }




    /**
     * Receives notification of the beginning of a BVars element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     * @see #endBVars
     */
    public void startBVars() throws OMException {
        //TraceContext("startBVars");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case CREATE_BIDING_VARIABLES:
                    pushContext(WAIT_FOR_VARIABLES);
                    break;
                    
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_APPLICATION:
                    throwOME("Malformed object. Application expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of the beginning of a BVars element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     * @see #startBVars
     */
    public void endBVars() throws OMException {
        //TraceContext("endBVars");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case WAIT_FOR_VARIABLES:
                    pushContext(CREATE_BIDING_OBJECT);
                    break;
                    
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_APPLICATION:
                    throwOME("Malformed object. Application expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }


    /**
     * Receives notification of the beginning of a Bind element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     * @see #endBind
     */
    public void endBind() throws OMException {
        //TraceContext("endBind");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case END_BIDING:
                    amto = amto.getFather();    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        switch (getContext()) {
                            case CREATE_OBJECT:
                                pushContext(WAIT_FOR_END_OBJECT);
                                break;
                            case CREATE_APPLICATION:
                            case CREATE_ERROR:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case WAIT_FOR_VARIABLES:
                                pushContext(CREATE_BIDING_OBJECT);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else
                        pushContext(WAIT_FOR_END_OBJECT);
                        
                    break;
                    
                case CREATE_OBJECT:
                case WAIT_FOR_OBJECT:
                case CREATE_APPLICATION:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
        
    }

    /**
     * Receives notification of the beginning of a error element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     * @see #endError
     */
    public void startError() throws OMException {
        //TraceContext("startError");
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_APPLICATION:
                    // *************************************************************
                    // Est-ce judicieux d'appliquer une erreur sur qque chose ??????
                    // *************************************************************
                    
                    // On rajoute un symbole foireux parce qu'on n'a pas créé une application à partir d'un symbol
                    // d'un CD. On n'a donc pas à tester a priori le nombre d'opérandes.
                    stackSymbol.push(new Symbol("", ""));
                    stackSymbolOperands.push(new Byte(Byte.MAX_VALUE));
                    
                case CREATE_OBJECT:
                    pushContext(context);
                case WAIT_FOR_OBJECT:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    pushContext(CREATE_ERROR);
                    
                    // Faudra créer l'objet adéquat !!!!
                    
                    break;
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of the end of an error element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see #startError
     */
    public void endError() throws OMException {
        //TraceContext("endError");
        
        if (!stackContext.empty()) {
            byte context = popContext();

            switch (context) {
                case WAIT_FOR_OBJECT:
                    /*
                    ce qu'il faut pour terminer l'erreur 
                    */
                    
                    // Ca fait que l'on vient de lire un object.
                    // I lfaut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        switch (getContext()) {
                            case CREATE_OBJECT:
                                pushContext(WAIT_FOR_END_OBJECT);
                                break;
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_ERROR:
                                //pushContext(WAIT_FOR_OBJECT);
                                // plutôt ça !!!
                                popContext();
                                popContext();
                                pushContext(WAIT_FOR_END_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case WAIT_FOR_VARIABLES:
                                pushContext(CREATE_BIDING_OBJECT);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else
                        pushContext(WAIT_FOR_END_OBJECT);
                        
                    break;
                    
                case CREATE_OBJECT:
                case CREATE_APPLICATION:
                case CREATE_BIDING:
                case CREATE_BIDING_OBJECT:
                    throwOME("Malformed object. An object was expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
        
    }


    /**
     * Receives notification of an Integer element.
     *
     * <p>By default, do nothing. Application writers may override this
     * method in a subclass.</p>
     *
     * @param value the value embeded in this Integer element. This is an infinite precision integer.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see fr.inria.openmath.omapi.BigInt
     */
    public void readInteger(BigInt value) throws OMException {
        //TraceContext("readInteger");
        Symbol symbol;
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_OBJECT:
                    insertInteger(value);
                    pushContext(WAIT_FOR_END_OBJECT);
                    break;
                case WAIT_FOR_OBJECT:
                    // Dans ce cas là, on peut venir de plusieurs états, notamment celui d'une application
                    // d'un symbole sur des opérandes. Il faut que l'on teste alors si l'arité dudit symbole
                    // est respectée ou pas. Pour les cas où une application n'est pas faite à partir d'un
                    // symbole, dans la pile des symboles, on AURA MIS UN SYMBOLE FOIREUX (new Symbol("", ""))
                    // POUR POUVOIR FAIRE LA DISTINCTION.
                    // Dans le cas contraire, on insère le symbole sans se poser de questions.
                    
                    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        
                        byte superContext = getContext();
                        if (superContext == CREATE_APPLICATION) {
                            Symbol currentSymbol = (Symbol) stackSymbol.peek();
                            
                            // d'abord on regarde si c'est un "vrai" symbol.
                            if (!currentSymbol.equals("", "")) {
                                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                                // byte arity = supportedCD.getSymbolArity(currentSymbol.getCD(), currentSymbol.getName());
                                byte arity = resourcesManager.getArity(currentSymbol.toString());
                                // Si l'arité est -1, alors on a un opérateur n-aire
                                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                                // On augmente le nombre d'opérandes
                                numOperands++;
                                if (numOperands > arity)
                                    throwOME("Malformed object. Symbol arity not respected", OMException.OME_SYNTAX);
                                    
                                stackSymbolOperands.push(new Byte(numOperands));
                            }
                        }
                        
                        insertInteger(value);
                        
                        switch (superContext) {
                            case CREATE_ERROR:
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else {
                        insertInteger(value);
                        pushContext(WAIT_FOR_END_OBJECT);
                    }
                        
                    break;
                    
                case CREATE_BIDING:
                    // A priori, le binder est un symbole, et non un entier
                    // Faudra voir si "extension totale" à la grammaire qui permet un objet OM (autre que <OMS.../>)
                    pushContext(context);
                    pushContext(CREATE_BIDING_VARIABLES);
                    break;
                case CREATE_BIDING_OBJECT:
                    insertInteger(value); // pourquoi pas.
                    popContext();  // on enlève le contexte CREATE_BIDING
                    pushContext(END_BIDING);
                    break;
                case CREATE_APPLICATION:
                    throwOME("Malformed application. Can't apply an Integer to something", OMException.OME_SYNTAX);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of a floating-point number element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @param value the value embeded in this Float element.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     */
    public void readFloat(double value) throws OMException {
        //TraceContext("readFloat");
        Symbol symbol;
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_OBJECT:
                    insertFloat(value);
                    pushContext(WAIT_FOR_END_OBJECT);
                    break;
                case WAIT_FOR_OBJECT:
                    // Dans ce cas là, on peut venir de plusieurs états, notamment celui d'une application
                    // d'un symbole sur des opérandes. Il faut que l'on teste alors si l'arité dudit symbole
                    // est respectée ou pas. Pour les cas où une application n'est pas faite à partir d'un
                    // symbole, dans la pile des symboles, on AURA MIS UN SYMBOLE FOIREUX (new Symbol("", ""))
                    // POUR POUVOIR FAIRE LA DISTINCTION.
                    // Dans le cas contraire, on insère le symbole sans se poser de questions.
                    
                    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        
                        byte superContext = getContext();
                        if (superContext == CREATE_APPLICATION) {
                            Symbol currentSymbol = (Symbol) stackSymbol.peek();
                            
                            // d'abord on regarde si c'est un "vrai" symbol.
                            if (!currentSymbol.equals("", "")) {
                                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                                // byte arity = supportedCD.getSymbolArity(currentSymbol.getCD(), currentSymbol.getName());
                                byte arity = resourcesManager.getArity(currentSymbol.toString());
                                // Si l'arité est -1, alors on a un opérateur n-aire
                                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                                // On augmente le nombre d'opérandes
                                numOperands++;
                                if (numOperands > arity)
                                    throwOME("Malformed object. Symbol arity not respected", OMException.OME_SYNTAX);
                                    
                                stackSymbolOperands.push(new Byte(numOperands));
                            }
                        }
                        
                        insertFloat(value);
                        
                        switch (superContext) {
                            case CREATE_ERROR:
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else {
                        insertFloat(value);
                        pushContext(WAIT_FOR_END_OBJECT);
                    }
                        
                    break;
                    
                case CREATE_BIDING:
                    // A priori, le binder est un symbole, et non un float
                    // Faudra voir si "extension totale" à la grammaire qui permet un objet OM (autre que <OMS.../>)
                    pushContext(context);
                    pushContext(CREATE_BIDING_VARIABLES);
                    break;
                case CREATE_BIDING_OBJECT:
                    insertFloat(value); // pourquoi pas.
                    popContext();  // on enlève le contexte CREATE_BIDING
                    pushContext(END_BIDING);
                    break;
                case CREATE_APPLICATION:
                    throwOME("Malformed application. Can't apply an Integer to something", OMException.OME_SYNTAX);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of a string element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @param value the value embeded in this String element.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     */
    public void readString(String value) throws OMException {
        //TraceContext("readString");
                
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_OBJECT:
                    //System.out.println("\t On insere la string dans l'arbre");
                    /*
                    Insertion de la string
                    }
                    */
                    pushContext(WAIT_FOR_END_OBJECT);
                    break;
                case WAIT_FOR_OBJECT:
                    //System.out.println("\t On insere la string dans l'arbre");
                    // Dans ce cas là, on peut venir de plusieurs états, notamment celui d'une application
                    // d'un symbole sur des opérandes. Il faut que l'on teste alors si l'arité dudit symbole
                    // est respectée ou pas. Pour les cas où une application n'est pas faite à partir d'un
                    // symbole, dans la pile des symboles, on AURA MIS UN SYMBOLE FOIREUX (new Symbol("", ""))
                    // POUR POUVOIR FAIRE LA DISTINCTION.
                    // Dans le cas contraire, on insère le symbole sans se poser de questions.
                    
                    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        
                        byte superContext = getContext();
                        if (superContext == CREATE_APPLICATION) {
                            // alors faut faire le teste de l'arité du symbol
                            
                            Symbol currentSymbol = (Symbol) stackSymbol.peek();
                            
                            // d'abord on regarde si c'est un "vrai" symbol.
                            if (!currentSymbol.equals("", "")) {
                                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                                // On augmente le nombre d'opérandes
                                numOperands++;
                                // byte arity = supportedCD.getSymbolArity(currentSymbol.getCD(), currentSymbol.getName());
                                byte arity = resourcesManager.getArity(currentSymbol.toString());
                                // Si l'arité est -1, alors on a un opérateur n-aire
                                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                                if (numOperands > arity)
                                    throwOME("Malformed object. Symbol arity not respected", OMException.OME_SYNTAX);
                                    
                                stackSymbolOperands.push(new Byte(numOperands));
                            }
                        }
                        
                        //System.out.println("\t On insere la string dans l'arbre");
                        
                        /*
                        insertion
                        */
                        
                        switch (superContext) {
                            case CREATE_ERROR:
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else {
                        // On insère directement ce que l'on vient de lire dans l'arbre
                        
                        /*
                        insertion.
                        */
                        
                        pushContext(WAIT_FOR_END_OBJECT);
                    }
                        
                    break;

                    
                case CREATE_BIDING:
                    //System.out.println("\t On insere la string dans l'arbre");
                    /*
                    Insertion de la string
                    */
                    pushContext(context);
                    pushContext(CREATE_BIDING_VARIABLES);
                    break;
                case CREATE_BIDING_OBJECT:
                    //System.out.println("\t On insere la string dans l'arbre");
                    /*
                    Insertion de la string
                    */
                    popContext();  // on enlève le contexte CREATE_BIDING
                    pushContext(END_BIDING);
                    break;
                case CREATE_APPLICATION:
                    //System.out.println("\t Création de l'application" + value);
                    pushContext(context);
                    pushContext(WAIT_FOR_OBJECT);
                    break;
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of a variable element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @param name the name of this Variable element.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     */
    public void readVariable(String name) throws OMException {
        //TraceContext("readVariable");
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_OBJECT:
                    amto.add("variable", name);
                    pushContext(WAIT_FOR_END_OBJECT);
                    break;
                case WAIT_FOR_OBJECT:
                    // Dans ce cas là, on peut venir de plusieurs états, notamment celui d'une application
                    // d'un symbole sur des opérandes. Il faut que l'on teste alors si l'arité dudit symbole
                    // est respectée ou pas. Pour les cas où une application n'est pas faite à partir d'un
                    // symbole, dans la pile des symboles, on AURA MIS UN SYMBOLE FOIREUX (new Symbol("", ""))
                    // POUR POUVOIR FAIRE LA DISTINCTION.
                    // Dans le cas contraire, on insère le symbole sans se poser de questions.
                    
                    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        
                        byte superContext = getContext();
                        if (superContext == CREATE_APPLICATION) {
                            // alors faut faire le teste de l'arité du symbol
                            Symbol currentSymbol = (Symbol) stackSymbol.peek();
                            
                            // d'abord on regarde si c'est un "vrai" symbol.
                            if (!currentSymbol.equals("", "")) {
                                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                                // On augmente le nombre d'opérandes
                                numOperands++;
                                // byte arity = supportedCD.getSymbolArity(currentSymbol.getCD(), currentSymbol.getName());
                                byte arity = resourcesManager.getArity(currentSymbol.toString());
                                // Si l'arité est -1, alors on a un opérateur n-aire
                                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                                if (numOperands > arity)
                                    throwOME("Malformed object. Symbol arity not respected", OMException.OME_SYNTAX);
                                    
                                stackSymbolOperands.push(new Byte(numOperands));
                            }
                        }
                        
                        amto.add("variable", name);
                        
                        switch (superContext) {
                            case CREATE_ERROR:
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else {
                        amto.add("variable", name);
                        pushContext(WAIT_FOR_END_OBJECT);
                    }
                        
                    break;

                    
                case CREATE_BIDING:
                    // A priori, le binder est un symbole, et non une variable
                    // Faudra voir si "extension totale" à la grammaire qui permet un objet OM (autre que <OMS.../>)
                    pushContext(context);
                    pushContext(CREATE_BIDING_VARIABLES);
                    break;
                case CREATE_BIDING_OBJECT:
                    amto.add("variable", name);
                    popContext();  // on enlève le contexte CREATE_BIDING
                    pushContext(END_BIDING);
                    break;
                case CREATE_APPLICATION:
                    // On insère un machin particulier
                    // Faudra voir plus tard avec function n variables
                    Symbol symbol = new Symbol("null", "user_function");
                    stackSymbol.push(symbol);
                    stackSymbolOperands.push(new Byte((byte) 0));
                    
                    insertFunction(name);
                    
                    pushContext(context);
                    pushContext(WAIT_FOR_OBJECT);
                    break;
                case WAIT_FOR_VARIABLES:
                    amto.add("variable", name);
                    pushContext(context);
                    break;
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of a byteArray element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @param value the value embeded in this ByteArray element.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     *
     */
    public void readByteArray(byte[] value) throws OMException {
        //TraceContext("readByteArray");        

        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_OBJECT:
                    //System.out.println("\t On insere le ByteArray dans l'arbre");
                    /*
                    insertion
                    */
                    pushContext(WAIT_FOR_END_OBJECT);
                    break;
                case WAIT_FOR_OBJECT:
                    // Dans ce cas là, on peut venir de plusieurs états, notamment celui d'une application
                    // d'un symbole sur des opérandes. Il faut que l'on teste alors si l'arité dudit symbole
                    // est respectée ou pas. Pour les cas où une application n'est pas faite à partir d'un
                    // symbole, dans la pile des symboles, on AURA MIS UN SYMBOLE FOIREUX (new Symbol("", ""))
                    // POUR POUVOIR FAIRE LA DISTINCTION.
                    // Dans le cas contraire, on insère le symbole sans se poser de questions.
                    
                    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        
                        byte superContext = getContext();
                        if (superContext == CREATE_APPLICATION) {
                            // alors faut faire le teste de l'arité du symbol
                            
                            Symbol currentSymbol = (Symbol) stackSymbol.peek();
                            
                            // d'abord on regarde si c'est un "vrai" symbol.
                            if (!currentSymbol.equals("", "")) {
                                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                                // On augmente le nombre d'opérandes
                                numOperands++;
                                // byte arity = supportedCD.getSymbolArity(currentSymbol.getCD(), currentSymbol.getName());
                                byte arity = resourcesManager.getArity(currentSymbol.toString());
                                // Si l'arité est -1, alors on a un opérateur n-aire
                                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                                if (numOperands > arity)
                                    throwOME("Malformed object. Symbol arity not respected", OMException.OME_SYNTAX);
                                    
                                stackSymbolOperands.push(new Byte(numOperands));
                                
                                // On regarde selon le type de l'opérateur si l'on doit envoyer des séparateurs ou pas.
                                //System.out.println("Test envoie d'un separateur");
                            }
                        }
                        
                        //System.out.println("\t On insere le ByteArray dans l'arbre");
                        
                        /*
                        insertion
                        */
                        
                        switch (superContext) {
                            case CREATE_ERROR:
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else {
                        // On insère directement ce que l'on vient de lire dans l'arbre
                        
                        /*
                        insertion.
                        */
                        
                        pushContext(WAIT_FOR_END_OBJECT);
                    }
                        
                    break;

                    
                case CREATE_BIDING:
                    //System.out.println("\t On insere le ByteArray dans l'arbre");
                    /*
                    insertion
                    */
                    pushContext(context);
                    pushContext(CREATE_BIDING_VARIABLES);
                    break;
                case CREATE_BIDING_OBJECT:
                    //System.out.println("\t On insere le ByteArray dans l'arbre");
                    /*
                    insertion
                    */
                    popContext();  // on enlève le contexte CREATE_BIDING
                    pushContext(END_BIDING);
                    break;
                case CREATE_APPLICATION:
                    throwOME("Malformed application. Can't apply a ByteArray to something", OMException.OME_SYNTAX);
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Attribute pairs expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ERROR:
                    throwOME("Malformed object. <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of a symbol element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @param value the value embeded in this Symbol element.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see Symbol
     */
    public void readSymbol(Symbol value) throws OMException {
        //TraceContext("readSymbol");
        byte errorCode;
        String typeOpe;
        
        // On teste la validité du symbole trouvé
        if (!resourcesManager.isValidSymbol(value.getCD(), value.getName())) {
            System.out.println("symbole pas valide : " + value.toString());
            throwOME("Malformed object. Invalid Symbol.", OMException.OME_SYNTAX);
        }
        
        /*
        if (!supportedCD.isValidSymbol(value.getCD(), value.getName())) {
            //throwOME("Malformed object. " + supportedCD.errorToString(), OMException.OME_NODE_NOT_FOUND);
            errorCode = supportedCD.getErrorCode();
            
            ControlException controlException;
            switch (errorCode) {
                case SupportedCD.INVALID_CD_NAME :
                    controlException = new ControlException("unknownCD");
                    controlException.setDetails(value);
                    throw new OMException(controlException);
                case SupportedCD.INVALID_SYMBOL_NAME :
                    controlException = new ControlException("unknownSymbol");
                    controlException.setDetails(value);
                    throw new OMException(controlException);
            }
        }
        */
        
        if (!stackContext.empty()) {
            byte context = popContext();
            
            switch (context) {
                case CREATE_APPLICATION:
                    pushContext(context);
                    // Le symbole existe. On regarde maintenant si le symbole peut être utilisé
                    // en tant qu'application
                    if (true /*supportedCD.isSymbolApplication(value.getCD(), value.getName())*/) {
                        insertSymbol(value);

                        // Gestion des symboles.
                        stackSymbol.push(value);
                        stackSymbolOperands.push(new Byte((byte) 0));
                            
                        pushContext(WAIT_FOR_OBJECT);
                    }
                    else
                        throwOME("Malformed application. " /*+ supportedCD.errorToString()*/, OMException.OME_SYNTAX);
                    break;
                    
                case CREATE_OBJECT:
                    insertSymbol(value);
                    pushContext(WAIT_FOR_END_OBJECT);
                    break;
                case WAIT_FOR_OBJECT:
                    // Dans ce cas là, on peut venir de plusieurs états, notamment celui d'une application
                    // d'un symbole sur des opérandes. Il faut que l'on teste alors si l'arité dudit symbole
                    // est respectée ou pas. Pour les cas où une application n'est pas faite à partir d'un
                    // symbole, dans la pile des symboles, on AURA MIS UN SYMBOLE FOIREUX (new Symbol("", ""))
                    // POUR POUVOIR FAIRE LA DISTINCTION.
                    // Dans le cas contraire, on insère le symbole sans se poser de questions.
                    
                    
                    // Ca fait que l'on vient de lire un object.
                    // Il faut regarder le contexte maintenant pour savoir dans quel état on passe.
                    if (!stackContext.empty()) {
                        
                        byte superContext = getContext();
                        if (superContext == CREATE_APPLICATION) {
                            // alors faut faire le teste de l'arité du symbol
                            Symbol currentSymbol = (Symbol) stackSymbol.peek();
                            
                            // d'abord on regarde si c'est un "vrai" symbol.
                            if (!currentSymbol.equals("", "")) {
                                // C'est un vrai symbol, on teste maintenant si l'arité est respectée
                                byte numOperands = ((Byte) stackSymbolOperands.pop()).byteValue();
                                // On augmente le nombre d'opérandes
                                numOperands++;
                                // byte arity = supportedCD.getSymbolArity(currentSymbol.getCD(), currentSymbol.getName());
                                byte arity = resourcesManager.getArity(currentSymbol.toString());
                                // Si l'arité est -1, alors on a un opérateur n-aire
                                arity = (arity == -1) ? Byte.MAX_VALUE : arity;
                                if (numOperands > arity)
                                    throwOME("Malformed object. Symbol arity not respected", OMException.OME_SYNTAX);
                                    
                                stackSymbolOperands.push(new Byte(numOperands));
                            }
                        }
                        
                        insertSymbol(value);
                        
                        switch (superContext) {
                            case CREATE_ERROR:
                            case CREATE_APPLICATION:
                                pushContext(WAIT_FOR_OBJECT);
                                break;
                            case CREATE_BIDING:
                                pushContext(CREATE_BIDING_VARIABLES);
                                break;
                            case CREATE_ATTRIBUT_PAIRS:
                                pushContext(END_ATTRIBUT_PAIRS);
                                break;
                            case CREATE_ATTRIBUTION:
                                pushContext(END_ATTRIBUTION);
                                break;
                        }
                    }
                    else
                        insertSymbol(value);
                        
                    break;
                    
                case CREATE_BIDING:
                    insertSymbol(value);
                    pushContext(context);
                    pushContext(CREATE_BIDING_VARIABLES);
                    break;
                case CREATE_BIDING_OBJECT:
                    insertSymbol(value);
                    popContext();  // on enlève le contexte CREATE_BIDING_OBJECT
                    popContext();  // on enlève le contexte CREATE_BIDING
                    pushContext(END_BIDING);
                    break;
                case CREATE_ATTRIBUT_PAIRS:
                case CREATE_ERROR:
                    /*
                    insertSymbol(value);
                    */
                    
                    /*
                    Pour le moment on ne fait que lever une exception, en retournant le symbole
                    correspondant à l'erreur qui a été transmise.
                    On verra par la suite comment on se débrouille avec ça.
                    */
                    //throw new RuntimeException(value.toString());
                    pushContext(context);
                    pushContext(WAIT_FOR_OBJECT);
                    break;
                case WAIT_FOR_END_OBJECT:
                    throwOME("Malformed object. End of object expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_ATTRIBUTION:
                    throwOME("Malformed object. <OMATP> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUT_PAIRS:
                    throwOME("Malformed object. Either </OMATP> or <OMS ...> expected", OMException.OME_NODE_NOT_FOUND);
                case END_ATTRIBUTION:
                    throwOME("Malformed object. </OMATTR> expected", OMException.OME_NODE_NOT_FOUND);
                case CREATE_BIDING_VARIABLES:
                    throwOME("Malformed object. <OMBVAR> expected", OMException.OME_NODE_NOT_FOUND);
                case WAIT_FOR_VARIABLES:
                    throwOME("Malformed object. Variables expected", OMException.OME_SYNTAX);
                case END_BIDING:
                    throwOME("Malformed object. </OMBIND> expected", OMException.OME_NODE_NOT_FOUND);
            }
        }
        else
            throwOME("Malformed object. Something wrong occured");
    }

    /**
     * Receives notification of a comment element.
     *
     * <p>By default, do nothing.  Application writers may override this
     * method in a subclass.</p>
     *
     * @param value the value embeded in this Comment element.
     * @exception fr.inria.openmath.omapi.OMException Any OpenMath exception.
     * @see Comment
     */
    public void readComment(String value) throws OMException {}
    
    /**
    * Inserts the symbol with the specified string representation.
    * @param symbolToString the specified string representation.
    */
    private void insertSymbol(String symbolToString) {
        String identifier = resourcesManager.getIdentifier(symbolToString);
        String val = resourcesManager.getValue(symbolToString);
        if (val.equals("null"))
            val = null;
            
        if (resourcesManager.getArity(symbolToString) == 0)
            amto.add(identifier, val);
        else
            amto = amto.add(identifier, val);
    }
    
    /**
    * Inserts the specified symbol.
    * @param symbol the specified symbol
    */
    private void insertSymbol(Symbol symbol) {
        insertSymbol(symbol.toString());
    }
    
    /**
    * Inserts the specified integer value.
    * @param value the specified integer.
    */
    private void insertInteger(BigInt value) {
        AbstractMathTreeObject tmpAmto = amto;
        
        if (value.getSign() != 1)
            tmpAmto = tmpAmto.add("unaryMinus", null);
        
        tmpAmto.add("integer", value.getDigits());
    }
    
    /**
    * Inserts the specified float value.
    * @param value the specified float.
    */
    private void insertFloat(double value) {
        AbstractMathTreeObject tmpAmto = amto;
        
        if (value < 0)
            tmpAmto = tmpAmto.add("unaryMinus", null);
        
        tmpAmto.add("float", "" + value);        
    }
    
    /**
    * Inserts the function with the specified name.
    * @param name the specified function name.
    */
    private void insertFunction(String name) {
        amto = amto.add("function", name);
    }
    
    /**
    * error must be : unhandledSymbol, or unknownCD or unknownSymbol
    *
    private void throwControlException(Symbol symbol, String error) throws OMException {
        ControlException controlException = new ControlException(error, symbol);
        throw new OMException(controlException);
    }*/
    
    private void TraceContext(String methodName) {
        System.out.println("\n\t\t <--");
        System.out.println("\t\t On entre dans la methode " + methodName);
        String str = (stackSymbol.empty() == true) ? "null" : ((Symbol) stackSymbol.peek()).toString();
        System.out.println("\t\t La valeur courante est " + str);
        str = (stackSymbolOperands.empty() == true) ? "null" : ""+((Byte) stackSymbolOperands.peek()).byteValue();
        System.out.println("\t\t Le nbre d'operandes est " + str );
        System.out.println("\t\t -->");
    }
    
    /**
    * Sets the event source.<BR>
    * Even if it is the instance which fires the events during the parsing, the instance (as a handler), just...
    * handles the parser. Basically, in a common sense, it is the parser which fires the events. We try to respect
    * the common sense by setting the right event source : the parser.
    * @param eventSource the event source
    */
    public void setEventSource(LinearParserEventSource eventSource) {
        mathExp.setEventSource(eventSource);
    }
}

